Starcor.S67.MVC = {};
Starcor.S67.MVC.DebugerModel = 'MVCDebuger';
Starcor.S67.MVC.Application = {
    models: {},
    views: {},
    controls: {},
    package: "/public/mvc",
    DATACHANGE: '$DataChange',
    addModel: function(model) {
        if (this.models[model.name]) {
            return this.models[model.name];
        } else {
            this.models[model.name] = model;
            return model;
        }
    },
    addView: function(view) {
        if (this.views[view.name]) {
            return this.views[view.name];
        } else {
            this.views[view.name] = view;
            return view;
        }
    },
    addControl: function(control) {
        if (this.controls[control.name]) {
            return this.controls[control.name];
        } else {
            this.controls[control.name] = control;
            return control;
        }
    },
    deleteModel: function(model) {
        if (this.models[model.name])
            delete this.models[model.name];
        else
            Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'model delete [' + model.name + '] not find!');
    },
    deleteView: function(view) {
        if (this.views[view.name])
            delete this.views[view.name];
        else
            Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'view delete [' + view.name + '] not find!');
    },
    deleteControl: function(control) {
        if (this.controls[control.name]) {
            delete this.controls[control.name];
        } else {
            Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'control delete [' + control.name + '] not find!');
        }
    },
    getModel: function(name) {
        if (this.models[name]) {
            return this.models[name];
        } else {
            Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'model get [' + name + '] not find!');
            return null;
        }
    },
    getView: function(name) {
        if (this.views[name]) {
            return this.views[name];
        } else {
            Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'view get [' + name + '] not find!');
            return null;
        }
    },
    getControl: function(name) {
        if (this.controls[name]) {
            return this.controls[name];
        } else {
            Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'control get [' + name + '] not find!');
            return null;
        }
    },
};


Starcor.S67.MVC.Application.Control = {
    disable: true,
    Check: function(view, action) {
        var actions = action.split('.');
        var control = view.control[actions[0]];
        if (!control) {
            if (this.disable === true) {
                control = new Starcor.S67.MVC.Control(actions[0]);
                control.actionMap = {};
                control.actionMap[Starcor.S67.MVC.Application.DATACHANGE] = actions[0] + '.' + Starcor.S67.MVC.Application.DATACHANGE;
                control.actionMap[actions[1]] = action;
                view.control[actions[0]] = control;
            } else {
                Starcor.S67.Debuger.error(Starcor.S67.MVC.DebugerModel, 'control [' + action + '] is empty!');
                return;
            }
        }
        if (!control.actionMap[actions[1]]) {
            if (this.disable === true) {
                control.actionMap[actions[1]] = action;
                view.control[actions[0]] = control;
            } else {
                Starcor.S67.Debuger.error(Starcor.S67.MVC.DebugerModel, 'control [' + action + '] is empty!');
                return;
            }
        }
    },
}
/******************自加载MVC数据*******************/
Starcor.S67.MVC.Application.preload = function(modelName, type) {
//    先检测有没有加载过，若没有则自加载 BY S67 20140514
	
    type = type == 'model' ? 'model' : 'control';
    
    if(type=='model'){
    	var model=Starcor.S67.MVC.Application.getModel(modelName);
    	if (model!==null){
    		return;
    	}
    }else if(type=='control'){
    	var control=Starcor.S67.MVC.Application.getControl(modelName);
    	if (control!==null){
    		return;
    	}
    }
    
    
    var control_id = modelName + '_' + type;

    if (document.getElementById(control_id) !== null) {
        Starcor.S67.Debuger.info(Starcor.S67.MVC.DebugerModel, 'preloadJS [' + type + '][' + modelName + '] is loaded!');
        return;
    }

    var control_path = Starcor.S67.MVC.Application.package + '/' + type + '/' + modelName + '.' + type + '.js';
    var preloadControl = new Starcor.S67.ajax();
    preloadControl.init(control_path, function(data) {
        if (data.header == 200 || data.header == 0 || data.header == 502) {
            __add_script(control_id, data.data);
        } else {
            Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'preload [' + control_path + '] failed! header is [' + data.header + ']');
        }
    }, true);

    function __add_script(id, data) {
        var Script = document.createElement("script");
        Script.type = "text/javascript";
        Script.id = id;
        Script.appendChild(document.createTextNode(data));
        document.head.appendChild(Script);
    }
};
/*****************开启MCV-V模式************** */
Starcor.S67.MVC.Application.VV = (function() {
    this.v_views = [];
    this.disabled = true;
    this.update = function() {
        if (this.disabled)
            return;
        var eles = Starcor.S67.$S.Tag("*");
        Starcor.S67.$S.each(eles, function(item, i) {
            if (item.hasAttribute("nw-view")) {
                self.v_views.push(self.createVView(item));
            }
        });

        return this;
    };
    this.disable = function() {
        this.disabled = true;
    };
    this.active = function() {
        this.disabled = false;
    };
    this.createVView = function(ele_view) {
        var v_view = {};
        var v_actions = [];
        v_view.name = ele_view.getAttribute('nw-view');
        var $actions = Starcor.S67.$S.Tag("*", ele_view);
        Starcor.S67.$S.each($actions, function(action, i) {
            if (action.hasAttribute("nw-action")) {
                var v_action = self.createVAction(action);
                var view = Starcor.S67.MVC.Application.getView(v_view.name);
                if (view) {
                    view.addEvent(v_action.action);
                }
                v_actions.push(v_action);
            }
        });
        v_view.action = v_actions;
        return v_view;
    };

    this.createVAction = function(ele_action) {
        var v_action = {};
        ele_action.style.display = 'none';
        v_action.action = ele_action.getAttribute('nw-action');
        var repeats = [];
        var $repeats = Starcor.S67.$S.Tag("*", ele_action);
        Starcor.S67.$S.each($repeats, function(repeat, i) {
            if (repeat.hasAttribute("nw-repeat")) {
                var v_repeat = {};
                v_repeat.dataBind = repeat.getAttribute("nw-repeat");
                v_repeat.html = Starcor.S67.$S.outterHTML(repeat);
                repeats.push(v_repeat);
            }
        });
        v_action.repeats = repeats;
        v_action.element = ele_action;
        v_action.html = ele_action.innerHTML;
        return v_action;
    };

    this.run = function(viewname, type, data) {
        if (this.disabled)
            return;
        Starcor.S67.$S.each(this.v_views, function(view, num) {
            if (view.name == viewname) {
                self.runAction(view, type, data);
            }
        });
    };

    this.runAction = function(view, type, data) {
        Starcor.S67.$S.each(view.action, function(action, num) {
            if (action.action == type) {
                self.freshData(action, data);
            }
        });
    };

    this.freshData = function(action, data) {
        var reg = /\{\{(.*?)\}\}/g;
        var repeatHtml = action.html;
        if (action.repeats.length > 0) {
            Starcor.S67.$S.each(action.repeats, function(repeat, num) {
                var replacehtml = self.freshRepeat(data, repeat);
                repeatHtml = repeatHtml.replace(repeat.html, replacehtml);
            });
        }

        repeatHtml = repeatHtml.replace(reg, function(regResult) {
            var basedataStr = self.getObjByStr(data, RegExp.$1);
            if (basedataStr) {
                return basedataStr;
            } else {
                return '';
            }
        });

        action.element.innerHTML = repeatHtml;
        action.element.style.display = '';
    };

    this.freshRepeat = function(data, repeat) {
        var reg = /\{\{(.*?)\}\}/g;
        var repeats = repeat.dataBind.split("|");
        var basedata = this.getObjByStr(data, repeats[0]);
        var repeatHtml = '';
        RegExp.multiline = true;
        Starcor.S67.$S.each(basedata, function(item, num) {
            // repeats[1]=item;
            var replaceStr = repeat.html;

            replaceStr = replaceStr.replace(reg, function(regResult) {
//				解决IE兼容问题
                /\{\{(.*?)\}\}/g.exec(regResult);
                var basedataStr = self.getObjByStr(data, RegExp.$1);
                if (basedataStr) {
                    return basedataStr;
                } else {
                    return self.getObjByStr(item, RegExp.$1);
                }
                ;
            });

            repeatHtml += replaceStr;
        });

        return repeatHtml;
    };

    this.getObjByStr = function(data, str) {
        var attrs = str.split(".");
        var obj = data;
        for (var i = 1; i < attrs.length; i++) {
            if (obj[attrs[i]]) {
                obj = obj[attrs[i]];
            } else {
                return '';
            }
        }
        return obj;
    };

    return this;
})();
/** ***************************MODEL************************************ */
Starcor.S67.MVC.Model = function(name) {
    var self = this;
    this.name = name;
//	Starcor.S67.MVC.Model.prototype.control = control;
    this.$data = {};
    Object.defineProperty(this, 'data', {
        set: function(x) {
            self.$data = x;
            self.disEvent(Starcor.S67.MVC.Application.DATACHANGE, self.$data);
        },
        get: function() {
            return self.$data;
        }
    });
    Starcor.S67.MVC.Application.addModel(this);
};
Starcor.S67.MVC.Model.prototype.free = function() {
    Starcor.S67.MVC.Application.deleteModel(this);
};
Starcor.S67.MVC.Model.prototype.refresh = function() {
    this.data = this.data;
};
Starcor.S67.MVC.Model.prototype.disEvent = function(type, data) {
    Starcor.S67.Debuger.info(Starcor.S67.MVC.DebugerModel, 'model [' + this.name + '] disEvent [' + type + ']');
    type = this.name + '.' + type;
    if (typeof data == 'object')
        data = Starcor.S67.$S.clone(data);
    Starcor.S67.$S.each(Starcor.S67.MVC.Application.controls, function(control, num) {
        control.disEvent(type, data);
    });
//	if (this.control)
//		this.control.disEvent(type, data);
};
/** ***************************VIEW************************************ */
Starcor.S67.MVC.View = function() {
    var self = this;
    var argnum = arguments.length;
    if (argnum < 1) {
        Starcor.S67.Debuger.error(Starcor.S67.MVC.DebugerModel, 'create view name is empty!');
        return;
    }

    this.name = arguments[0];
    this.control = {};

    if (Starcor.S67.MVC.Application.Control.disable === false) {
        if (argnum == 1) {
            __add_control(arguments[0]);
        } else {
            Starcor.S67.$S.each(arguments, function(arg, num) {
                if (num == 0)
                    return;
                __add_control(arg);
            });
        }
    }

    Starcor.S67.MVC.Application.addView(this);

    function __add_control(controlName) {
        Starcor.S67.MVC.Application.preload(controlName, 'control');
        var control = Starcor.S67.MVC.Application.getControl(controlName);
        if (control)
            self.control[controlName] = control;
    }

};
Starcor.S67.MVC.View.prototype.free = function() {
    Starcor.S67.MVC.Application.deleteView(this);
};
Starcor.S67.MVC.View.prototype.call = function(action, params) {
    var actions = action.split('.');
    if (actions.length < 2) {
        Starcor.S67.Debuger.error(Starcor.S67.MVC.DebugerModel, 'view [' + this.name + '] call [' + action + ']  is wrong!');
        return;
    }

    Starcor.S67.MVC.Application.Control.Check(this, action);
    if (this.control && this.control[actions[0]]) {
        this.control[actions[0]].call(actions[1], params);
    } else {
        Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'view [' + this.name + '] control [' + actions[0] + '] is empty!');
    }

};
Starcor.S67.MVC.View.prototype.removeEvent = function(type, callback) {
    var selfname = this.name;
    var types = type.split('.');
    if (types.length < 2) {
        Starcor.S67.Debuger.error(Starcor.S67.MVC.DebugerModel, 'view [' + this.name + '] removeEvent [' + type + ']  is wrong!');
        return;
    }

    if (!this.control || !this.control[types[0]]) {
        Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'view [' + this.name + '] removeEvent [' + type + '] is empty!');
        return;
    }

    var func_key = '';
    if (typeof callback == 'function') {
        func_key = Starcor.S67.MD5.hex_md5(callback.toString());
    }

    this.control[types[0]].disEventer.remove(this, type, func_key);

};
Starcor.S67.MVC.View.prototype.addEvent = function(type, callback) {
    var selfname = this.name;
    var types = type.split('.');
    if (types.length < 2) {
        Starcor.S67.Debuger.error(Starcor.S67.MVC.DebugerModel, 'view [' + this.name + '] addEvent [' + type + ']  is wrong!');
        return;
    }
    Starcor.S67.MVC.Application.Control.Check(this, type);

    if (!this.control || !this.control[types[0]]) {
        Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'view [' + this.name + '] addEvent [' + type + '] is empty!');
        return;
    }

    var func_key = '';
    if (typeof callback == 'function') {
        func_key = Starcor.S67.MD5.hex_md5(callback.toString());
    }

    this.control[types[0]].disEventer.add(this, type, function(data) {
        if (callback)
            callback(data);
        Starcor.S67.MVC.Application.VV.run(selfname, type, data);
    }, func_key);
};

/** ***************************Control************************************ */
Starcor.S67.MVC.Control = function(name) {
    this.name = name;
    this.actionMap = {};
    Starcor.S67.MVC.Application.addControl(this);
};
Starcor.S67.MVC.Control.prototype.free = function() {
    Starcor.S67.MVC.Application.deleteControl(this);
};
Starcor.S67.MVC.Control.prototype.call = function(action, params) {
    var modelAction = this.actionMap[action];
    if (!modelAction) {
        Starcor.S67.Debuger.error(Starcor.S67.MVC.DebugerModel, 'Control [' + this.name + '] call [' + action + '] is empty!');
        return;
    }

    var actions = modelAction.split('.');
    
   

   	Starcor.S67.MVC.Application.preload(actions[0], 'model');
     var model = Starcor.S67.MVC.Application.getModel(actions[0]);
    if (model !== null) {
        var func = model[actions[1]];
        if (func && typeof (func) == 'function') {
            func(params);
        } else {
            Starcor.S67.Debuger.warning(Starcor.S67.MVC.DebugerModel, 'Control [' + this.name + '] call model [' + model.name + '][' + actions[1] + '] is wrong!');
        }
    }
};
Starcor.S67.MVC.Control.prototype.disEvent = function(type, data) {
    var actionType;
    Starcor.S67.$S.each(this.actionMap, function(action, attr) {
        if (action == type) {
            actionType = attr;
            return true;
        }
    });
    if (!actionType) {
        Starcor.S67.Debuger.info(Starcor.S67.MVC.DebugerModel, 'Control [' + this.name + '] disEvent [' + type + '] is not find !');
        return;
    }
    var action_key = this.name + "." + actionType;
    var viewlist = this.disEventer.get(action_key);
    if (viewlist !== null) {
        Starcor.S67.$S.each(viewlist, function(item, num) {
            Starcor.S67.$S.each(item.callback, function(func, i) {
                Starcor.S67.Debuger.info(Starcor.S67.MVC.DebugerModel, 'view [' + item.view.name + '] callback [' + action_key + '] !');
                if (typeof (func) == 'function')
                    func(data);
            });
        });
    }
};
Starcor.S67.MVC.Control.prototype.disEventer = (function() {
    this.arr = {};
    this.add = function(view, type, callback, key) {
        if (this.arr[type]) {
            var exists = false;
            Starcor.S67.$S.each(this.arr[type], function(item, num) {
                if (item.view.name == view.name) {
                    if (key && callback) {
                        item.callback.push(callback);
                        item.key.push(key);
                    }
                    exists = true;
                    return exists;
                }
            });
            if (exists)
                return;
            else
                this.arr[type].push({
                    view: view,
                    callback: [callback],
                    key: [key]
                });
        } else {
            this.arr[type] = [];
            this.arr[type].push({
                view: view,
                callback: [callback],
                key: [key]
            });
        }
    };
    this.remove = function(view, type, key) {
        if (this.arr[type]) {
            Starcor.S67.$S.each(this.arr[type], function(item, num) {
                if (item.view.name == view.name) {
                    var i = Starcor.S67.$S.index(item.key, key);
                    if (i == -1) {
                        Starcor.S67.Debuger.info(Starcor.S67.MVC.DebugerModel, 'View [' + view.name + '] removeEvent [' + type + '] is not find !');
                    } else {
                        item.callback.splice(i, 1);
                        item.key.splice(i, 1);
                    }
                    return true;
                }
            });
        }
    };
    this.get = function(type) {
        if (this.arr[type]) {
            return this.arr[type];
        } else {
            return null;
        }
    };
    return this;
})();
